Public
Edited
Oct 16, 2024
Paused
19 forks
1 star
Insert cell
Insert cell
Insert cell
animalData = d3.csv("https://magrawala.github.io/cs448b-fa20/assets/docs/animals.csv", function(d) {
return {
// We parse the data into an array of csv objects. We could for example change the names of fields.
id: +d.id,
animal: d.animal,
weight: +d.weight,
height: +d.height,
name: d.name
};
}).then(function(animalData) {
//Outside of Observable notebooks you would put all code to draw the graph here.
return animalData;
});

Insert cell
printTable(animalData)
Insert cell
Insert cell
Insert cell
Insert cell
plotVars = (
{plotWidth: 200, //Width of plot region
plotHeight: 200, //Height of plot region
plotMargin: 50, //Margin space for axes and their labels
plotCircleRadius: 5 //Radius in pixels of circles in the plot
}
);
Insert cell
Insert cell
xScale = d3.scaleLinear()
.domain([0, 10])
.range(/* fill in */);
Insert cell
yScale = d3.scaleLinear()
.domain([0, 10])
.range(/* fill in */); //Flip y-range to deal with SVG origin at top,left
Insert cell
xScale(5)
Insert cell
Insert cell
function drawScatterPlot(animalData, plotContainer) {
plotContainer.selectAll(/* fill in */) //select all of the SVG 'circle' elements in the plotContainer
.data(/* fill in */) //bind the data, using d.id as the key
.join(
enter => enter.append(/* fill in */), //append an svg 'circle' element for each entering data item
update => update, //do nothing with data items that match existing items
exit => exit.remove() //remove svg 'circle' elements whose data is now gone.
)
.attr('r', /* fill in */) //use plotVars.plotCircleRadius
.attr('cx', /* fill in */) //base on d.weight
.attr('cy', /* fill in */) //base d.height
.attr('fill', function (d) { //set to steelblue if d.animal='cat', salmon if d.animal='dog'
return /* fill in */
})
}
Insert cell
Insert cell
{
let svgPlotContainer = d3.create('svg')
.attr('width',plotVars.plotWidth)
.attr('height',plotVars.plotHeight)
.style('background-color', 'whitesmoke'); //Color container bg to see its extent
// drawScatterPlot(animalData, svgPlotContainer);
return svgPlotContainer.node();
}
Insert cell
Insert cell
Insert cell
function createAxes(plotContainer) {

const xAxis = plotContainer.append('g') //create SVG <g> elt for x-axis
.attr('transform', `translate(0,${plotVars.plotHeight})`) //translate to bottom of plot
.call(d3.axisBottom(xScale)); //use axisBottom to form ticks below
const yAxis = plotContainer.append('g') //create SVG <g> elt for y-axis
.call(d3.axisLeft(yScale)); //use axisLeft to form ticks to the left
const xAxisLabel = plotContainer.append("text")
.attr("transform", `translate(${plotVars.plotWidth/2}, ${plotVars.plotHeight + 35})`)
.style("text-anchor", "middle")
.text("Weight");
const yAxisLabel = plotContainer.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - plotVars.plotMargin)
.attr("x",0 - (plotVars.plotHeight / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Height");
}
Insert cell
Insert cell
{
let svgPlotContainer = d3.create('svg')
.attr('width',plotVars.plotWidth)
.attr('height',plotVars.plotHeight)
.style('background-color', 'whitesmoke');
//createAxes(svgPlotContainer);
//drawScatterPlot(animalData, svgPlotContainer);

return svgPlotContainer.node()
}
Insert cell
Insert cell
Insert cell
function createWholeChartContainer() {
const outerWidth = /* fill in */; // extend plotWidth by twice plotMargin
const outerHeight = /* fill in */; // extend plotHeight by twice plotMargin
var wholeChartContainer = d3.create('svg')
.attr('width', outerWidth)
.attr('height',outerHeight)
.style('background-color', 'whitesmoke')
wholeChartContainer.append('g')
// Translate g element by plotMargin, plotMargin to place inner plotting region.
.attr('transform', `translate(${plotVars.plotMargin},${plotVars.plotMargin})`)
.attr('id', 'plotContainer'); //Give the plot container an id so we can access it later.
return wholeChartContainer;

}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//Add rect to plotContainer of size plotWidth x plotHeight to visualize it
//plotContainer.append('rect')
//.attr('width',plotVars.plotWidth)
//.attr('height',plotVars.plotHeight)
//.attr('fill','burlywood');
return wholeChartContainer.node();
}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//createAxes(plotContainer);
//drawScatterPlot(animalData, plotContainer);

return wholeChartContainer.node()
}
Insert cell
Insert cell
function drawScatterPlotMO(animalData, plotContainer) {
plotContainer.selectAll('circle')
.data(animalData, d=>d.id)
.join('circle')
//Set attributes for entering and updating elements
.attr('r',plotVars.plotCircleRadius)
.attr('cx',function(d){ return xScale(d.weight); })
.attr('cy',function(d){ return yScale(d.height); })
.attr('fill', function (d) {
return d.animal === 'cat' ? 'steelblue' : 'salmon'
})
.on('mouseover', function (event, d) { //Handle 'mouseover' events
plotContainer.append(/* fill in */) //Append SVG 'text' element.
.attr('class', /* fill in */) //Set class to 'ptLabel' so can remove easily later
.attr('x', /* fill in */) //Set label position near its circle xScale(d.weight)
.attr('y', /* fill in */) //Set label position near its circle yScale(d.height)
.text(d.name);
})
.on('mouseout', function(event, d) {
plotContainer.selectAll(/* fill in */).remove() // Remove all ptLabels
});
}
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');
//createAxes(plotContainer);
//drawScatterPlotMO(animalData, plotContainer);

return wholeChartContainer.node()
}
Insert cell
Insert cell
html`
<html>
<head>
</head>
<body>
<h2>Height vs. Weight for Cats & Dogs</h2>
<span> Filter Buttons: </span>
<button id='cats-only' data-filter='cat' style='background-color: steelblue'>
Cats Only
</button>
<button id='dogs-only' data-filter='dog' style='background-color: salmon'>
Dogs Only
</button>
<button id='both' data-filter='both' style='background-color: gray'>
Both
</button>
<div id ="animal-vis"></div>
</body>
</html>
`
Insert cell
Insert cell
function handleButtons(animalData, plotContainer) {
let buttons = d3.selectAll('button');
buttons.on('click', function() { // Add 'click' event listeners and handlers
// In function working with D3 selection, 'this' refers to the current DOM node
let chosenAnimal = this.dataset.filter; //Value of the 'data-filter' attr of the button.
let newData = animalData;
if (chosenAnimal !== 'both') {
newData = animalData.filter(d => d.animal === chosenAnimal);
}
drawScatterPlotMO(newData, plotContainer);
});
}
Insert cell
Insert cell
{
let wholeChartContainer = createWholeChartContainer();
let plotContainer = wholeChartContainer.select('#plotContainer');

//createAxes(plotContainer);
//drawScatterPlotMO(animalData, plotContainer);
//handleButtons(animalData,plotContainer);
//Attach the node we created using d3.create() to the part of the DOM we setup using HTML above.
d3.select('#animal-vis').selectAll("*").remove(); //Remove any plots that may already have been created.
d3.select('#animal-vis').append( () => /* fill in */); //Attach wholeChartContainer.node() to DOM;
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require('d3@7')
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more